<template>
  <a-modal
    :title="title"
    :visible="visible"
    :width="870"
    :destroy-on-close="true"
    centered
    @cancel="handleCancel"
  >
    <div class="formual-item-row">
      <span style="margin-right: 14px;">数据表：</span>
      <a-select
        :default-value="defaultSelection"
        :show-search="true"
        style="width: 200px;"
        @change="handleSelectChange"
      >
        <span slot="suffixIcon">{{
          selectedType === 'dataset'
            ? '(数据集)'
            : selectedType === 'task'
            ? '(Pipeline)'
            : ''
        }}</span>
        <a-select-opt-group>
          <span slot="label">数据集</span>
          <a-select-option
            v-for="item in dataList.dataset"
            :key="item.id"
            :type="item.type"
            :name="item.tableName"
            :value="`data-${item.name}`"
          >
            {{ item.name }}
          </a-select-option>
        </a-select-opt-group>
        <a-select-opt-group label="Pipeline">
          <template v-for="item in dataList.pipeline">
            <a-select-option
              v-if="item.type"
              :key="item.id"
              :type="item.type"
              :name="item.tableName"
              :value="`pipe-${item.name}`"
            >
              {{ item.name }}
            </a-select-option>
          </template>
        </a-select-opt-group>
      </a-select>
    </div>
    <div class="formual-item-row">
      <span style="margin-right: 28px;">公式：</span>
      <div style="flex: 1;">
        <formula-box
          :formula-err="formulaErr"
          :formula-value="formulaBody"
          :column-list="tableColumnList"
          from="vis-system"
          @update:value="updateValue"
        >
        </formula-box>
      </div>
    </div>
    <div class="formual-item-row">
      <span>小数位数：</span>
      <a-input-number v-model="precisionNum" style="flex: 1;" :min="0" :max="9">
      </a-input-number>
    </div>
    <div class="tableBox comp-data-table">
      <simple-virtual-table
        v-if="tableColumns && tableColumns.length > 0"
        ref="virtualTable"
        column-key="name"
        :data-sources="tableData"
        :data-column="tableColumns"
        :height="height"
      >
        <template #header="{column}">
          <span class="data-cell">{{ column.name }}</span>
        </template>

        <template #cell="{column, row, index:$index}">
          <div style="height: 100%;">
            <span
              :index="$index"
              :class="{
                'data-cell': true,
              }"
            >
              <!-- 这一层用于触发刷选,请确保内容最后包含一个空格 -->
              <span
                class="cell-hilight"
                :title="row[column.name.slice(column.name.indexOf('-') + 2)]"
                >{{ row[column.name.slice(column.name.indexOf('-') + 2)] }}
              </span>
            </span>
          </div>
        </template>
      </simple-virtual-table>
    </div>

    <template slot="footer">
      <a-button key="back" @click="handleCancel">
        取消
      </a-button>
      <a-button key="submit" :loading="loading" @click="handleOk(false)">
        保存
      </a-button>
      <a-button
        key="submitAndInsert"
        type="primary"
        :loading="loading"
        @click="handleOk(true)"
      >
        保存并插入
      </a-button>
    </template>
  </a-modal>
</template>

<script lang="ts">
import { Vue, Prop, Component, Emit, Watch } from 'vue-property-decorator'
import SimpleVirtualTable from '@/components/simple-virtual-table/Table.vue'
import {
  queryWidgetData,
  parseGetDataResult,
} from '@/components/common/VisualizationDashboard/util'
import VisualizationStore from '@/store/modules/visualization'
import { IColumn } from '@/components/common/VisualizationDashboard/interface'
import { addFormula, updateFormula } from '@/api/widget'
import FormulaBox from '../../views/studio/vr-operations/columns/formulaBox.vue'

interface EditFormula {
  id: number
  name: string
  formula: string
  result: string
  taskId: number
  type: string
  tableName: string
  precisionNum: number
}

@Component({
  components: {
    FormulaBox,
    SimpleVirtualTable,
  },
})
export default class EditFormulaModal extends Vue {
  @Prop() title!: string
  @Prop() visible!: boolean
  @Prop({ default: () => ({}) }) item?: any
  @Prop() dataList!: any

  private formulaErr: string = ''
  private formulaBody: string = '' //  公式内容
  private formulaResult: string = '' //  公式结果
  private name: string = '' //  所选数据集名称
  private taskId: Number = 0
  private tableName: string = '' //    数据集table name
  private formulaId: Number = 0 //  公式id
  private selectedType: string = '' //  所选数据集类型
  private defaultSelection = '' //  编辑状态下，默认的选择
  private detectFormulaInText: any = [] //
  private loading: boolean = false
  private precisionNum: Number = 2

  public get height() {
    return 288
  }

  @Watch('visible')
  clearTableData() {
    this.tableData = []
    this.tableColumns = []
    this.defaultSelection = ''
    this.formulaBody = ''
    this.formulaErr = ''
    this.selectedType = ''
    this.precisionNum = 2
  }

  //  编辑状态
  @Watch('item', {
    immediate: true,
    deep: true,
  })
  handleFormulaVal(newValue: EditFormula) {
    const itemArray = Object.keys(newValue)
    if (itemArray.length > 0) {
      this.tableColumnList = []
      this.formulaBody = newValue.formula
      this.defaultSelection = newValue.name
      this.formulaId = newValue.id
      this.precisionNum = newValue.precisionNum

      // rewrite select param
      this.name = newValue.name
      this.taskId = newValue.taskId
      this.tableName = newValue.tableName
      this.selectedType = newValue.type

      setTimeout(() => {
        this.queryTableData()
      }, 500)
    }
  }

  //  是否删除的公式被文本组件引用
  private checkIfExistFormula(targetId: number) {
    this.detectFormulaInText = []
    const elements = document.querySelectorAll('.mceNonEditable')
    if (elements.length > 0) {
      // eslint-disable-next-line no-restricted-syntax
      for (const item of elements) {
        const id = item.getAttribute('data-id')
        if (targetId === Number(id)) {
          this.detectFormulaInText.push(item)
        }
      }
      if (this.detectFormulaInText.length > 0) {
        return true
      }
    }
    return false
  }

  private updateFormulaInText(result: any) {
    VisualizationStore.setUpdateFormula(result)
  }

  private handleUpdateFormula() {
    return updateFormula({
      data: {
        name: this.name,
        projectId: this.$route.params.id,
        taskId: this.taskId,
        formula: this.formulaBody,
        precisionNum: this.precisionNum === null ? 2 : this.precisionNum,
        type: this.selectedType,
        formulaId: this.formulaId,
        tableName: this.tableName,
      },
    })
  }

  //  新增 / 更新公式
  @Emit('close')
  private async handleOk(ifInsert: boolean = false) {
    this.loading = true
    const that = this
    const itemArray = Object.keys(this.item)
    let response: any
    if (itemArray.length === 0) {
      //  新增公式
      response = await addFormula({
        data: {
          name: this.name,
          projectId: this.$route.params.id,
          taskId: this.taskId,
          formula: this.formulaBody,
          precisionNum: this.precisionNum === null ? 2 : this.precisionNum,
          type: this.selectedType,
          tableName: this.tableName,
        },
      })
    } else {
      //  更新公式
      response = await that.handleUpdateFormula()
      if (
        response.data.result.status === 'SUCCESS' &&
        itemArray.length > 0 &&
        this.checkIfExistFormula(this.item.id)
      ) {
        that.updateFormulaInText({
          formula: this.formulaBody,
          id: this.item.id,
          result: response.data.result.result,
        })
        that.$message.info('文本中的公式也将更新')
      }
    }
    this.loading = false
    const { result } = response.data
    if (result.status === 'SUCCESS') {
      //  fetch
      this.formulaResult = result.result
      VisualizationStore.fetchFormulaList({
        projectId: Number(this.$route.params.id),
      })
      if (ifInsert) {
        //  增加insert formula ；
        VisualizationStore.updateInsertFormula({
          formula: this.formulaBody,
          id: result.formulaId,
          result: this.formulaResult,
        })
      }
      return false
    }
    if (result.status === 'FAIL') {
      this.formulaErr = result.logInfo.error_msg
        ? JSON.parse(result.logInfo).error_msg
        : result.logInfo
    }

    this.$message.error('添加公式失败')
    return true
  }

  @Emit('close')
  private async handleCancel() {
    return false
  }

  private tableData: any = []
  private tableColumns: any = []
  //  存放所选数据集的列信息列表 - 用于公式$ 展示
  public tableColumnList: Array<string> = []

  public updateValue(value: string) {
    this.formulaBody = value
    this.formulaErr = ''
  }

  //  获取对应数据集的数据
  public async queryTableData() {
    //  复用fanfan table data 的接口
    const parameters = {
      id: this.taskId, //  node taskId
      tableJson: {
        curPage: 1,
        filter: [],
        name: '_record_id_',
        pageSize: 20,
      },
      type: this.selectedType, //  node type dataset
    }
    const resultValue: {
      columns: IColumn[]
      data: any[]
      page?: { curPage: number; pageSize: number; totalElements: number }
    } = await queryWidgetData(parameters)
    const { columns } = resultValue
    this.tableData = parseGetDataResult(resultValue)

    //  去除record id column [refactor columns]
    const pop = columns.filter((item: any) => {
      return item.name !== '_record_id_'
    })
    //  重命名column name as Cx - ....
    pop.forEach((item: any, index: any) => {
      item.name = `c${index + 1} - ${item.name}`
      this.tableColumnList.push(item.name)
    })
    this.tableColumns = pop
  }

  public async handleSelectChange(value: any, option: any) {
    //  clear list
    this.tableColumnList = []
    //  rewrite select param, remove pipe-.. / data-..
    this.name = value.slice(5)
    this.tableName = option.data.attrs.name
    this.taskId = option.data.key
    this.selectedType = option.data.attrs.type

    this.queryTableData()
  }
}
</script>

<style lang="less" scoped>
.formual-item-row {
  align-items: baseline;
  display: flex;
  justify-content: center;
  margin-bottom: 16px;
  padding: 0 196px 0 135px;
}

/deep/ .ant-select {
  flex: 1;
}

.tableBox {
  padding: 5px 32px 0;
}

.comp-data-table {
  /deep/ .plTableBox .el-table--mini td,
  /deep/ .plTableBox .el-table td {
    padding: 0;
  }

  /deep/ .plTableBox tr {
    th .cell {
      white-space: nowrap;
    }

    .cell {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  /deep/ .plTableBox td {
    .cell {
      padding-left: 0 !important;
      padding-right: 0 !important;

      .data-index {
        padding-left: 8px;
      }

      .data-cell .cell-content {
        padding-left: 8px;
        padding-right: 8px;
      }
    }
  }

  /deep/ .plTableBox .el-table td {
    background: transparent;
  }

  /deep/ .plTableBox .el-table tr {
    background: #fafafc;

    &:nth-child(2n) {
      background: #f3f3f3;
    }
  }

  /deep/ .plTableBox .has-gutter {
    .is-select-column {
      background: rgb(238, 239, 252) !important;
    }

    th .cell {
      color: #5d637e;
      font-family: 'Microsoft YaHei', '微软雅黑', 'Arial Narrow', Arial,
        sans-serif;
      font-size: 12px;
    }
  }

  /deep/ .table-cell {
    border-top: 1px solid #ebeef5;
  }

  /deep/ .data-cell {
    display: block;
    height: 100%;
    overflow: hidden;
    padding: 6px 10px;
    position: relative;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 100%;

    .cell-content {
      display: block;
      height: auto;
      overflow: hidden;
      pointer-events: none;
      position: relative;
      text-overflow: ellipsis;

      &.null {
        color: transparent;
      }
    }

    .cell-common {
      display: block;
      height: auto;
      overflow: hidden;
      padding: 0 8px;
      pointer-events: all;
      position: relative;
      text-overflow: ellipsis;
      user-select: text;
    }
  }
}
</style>
